package com.tul.exercise.base.java8.lambda;

import com.tul.exercise.base.java8.stream.base.Artist;
import com.tul.exercise.base.java8.stream.base.Person;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;

/**
 * 函数接口示例
 *
 * @author tuliang
 */
public class FunctionTest {
    @Test
    @DisplayName("")
    public void test01() {
        // Predicate 接口使用

        // 1) 将一个lambda表达式付给Predicate接口
        Predicate<Artist> isFromChina = (Artist artist) -> artist.getFrom().equals("China");
        List<Artist> artistList = Artist.createArtists(1);
        artistList.stream().forEach(artist -> System.out.println(isFromChina.test(artist)));

        Predicate<Artist> isBank = Artist::isBank;
        Artist artist2 = new Artist();
        System.out.println(isBank.test(artist2));


        Consumer<Artist> printInfo;

        printInfo = Artist::toString;
        printInfo.accept(artist2);

        Predicate<Person> isMam = Person::isMam;

        List<Artist> a1 = Artist.createArtists(10);
        List<Person> p = Person.createPersons(3);
        List<Artist> mans = a1.stream().filter(a -> isMam.test(a)).collect(Collectors.toList());
        System.out.println(mans);

        Function<Person, String> getName = Person::getName;
        List<String> names = a1.stream().map(artist -> getName.apply(artist))
                .collect(Collectors.toList());
        System.out.println(names);

        a1.stream().filter(a -> isMam.test(a)).count();


        //a1.stream().reduce();

    }

    @Test
    @DisplayName("类型推断")
    public void test02() {
        // x类型自动推断为Double
        Predicate<Double> f1 = x -> x > 3.0;
        // y的类型自动推断为Long
        Predicate<Long> f2 = y -> y > 1000L;


        // 自动推断出x、y的类型为Long
        BinaryOperator<Long> addLong = (x, y) -> x + y;
        BinaryOperator<Double> multDouble = (a, b) -> a * b;

        // 自动推断无法推断处n、m的类型
        //BinaryOperator add = (n,m) ->n + m;
    }

    @Test
    @DisplayName("自定义接口抛出异常")
    public void test03() {

        DoubleDiv div = (a, b) -> a / b;

        Stream.of(0.0, 1.9).forEach(n -> {
            System.out.println(div.apply(4.0,n));
        });

        System.out.println(div.apply(-8.9,0));

        //List<Double> list = Stream.of(0, 1.9).collect(Collectors.toList());

        //  DoubleStream list = Stream.of(0, 2.0, 4.8).mapToDouble(Double::new);

    }

    @Test
    @DisplayName("函数接口抛出异常")
    public void test04() {
        // Double类型的除法
        BinaryOperator<Double> div = (a, b) -> {
            double result;
            try {
                result = a /b;
            } catch (Exception e) {
                if (a >0) {
                    result = Double.POSITIVE_INFINITY;
                } else {
                    result = Double.NEGATIVE_INFINITY;
                }
            }
            return result;
        };

        double n = 4;
        Stream.of(0.0, 2.9, -3.9).forEach(a -> System.out.println(div.apply(n, a)));

        double m = -4;
        Stream.of(0.0, 2.9, -3.9).forEach(a -> System.out.println(div.apply(m, a)));
    }
}
